package edu.ecut.cs.ai.status;

import java.util.ArrayList;
import java.util.List;

public class Travel implements Status {
	static final int initStatus[] = {2,1};
	static final int targetStatus[] = {2, 4};
	Travel parent;
	int[] numbers;
	int g;
	double h;

	@Override
	public void getInitStatus(boolean randomly) {
		parent = null;
		if (randomly) {
			int nums[] = new int[2];
			do {
				for (int i = 0; i < 2; i++) {
					nums[i] = (int)(Math.random()*4);
				}
			} while (isForbidden(nums));
			numbers = nums;
		} else {
			numbers = initStatus;
		}
		g = 0;
		setHValue();  
	}
	
	private boolean isForbidden(int[] s) {
		return (s[0] < 1 || s[0] > 4) || 
				(s[1] < 1 || s[1] > 4) ||
				(s[0] == 2 || s[0] == 3) && s[1] == 2;
	}

	@Override
	public List<Status> getChildren() {
		List<Status> r = new ArrayList<Status>();
		Travel child;
		int ops[] = {-1, 0, 1};
		for (int i: ops) {
			for (int j: ops) {
				if (i != 0 || j != 0) {
					child = new Travel();
					child.parent = this;
					child.numbers = this.numbers.clone();
					child.numbers[0] += i;
					child.numbers[1] += j;
					if (!isForbidden(child.numbers)) {
						if (i == 0 || j == 0) {
							child.g = g + 10;
						} else {
							child.g = g + 14;
						}					
						child.setHValue();
						r.add(child);
					}
				}
			}
		}
		return r;
	}

	@Override
	public Status getParent() {
		return parent;
	}

	@Override
	public boolean sameAs(Status s) {
		boolean r = true;
		
		if (s instanceof Travel) {	
			Travel other = (Travel)s;
			for (int i = 0; i < 2; i++) {
				if (this.numbers[i] != other.numbers[i]) {
					r = false;
					break;
				}
			}
		} else {
			r = false;
		}
		
		return r;
	}

	@Override
	public boolean isTargetStatus() {
		boolean r = true;
		
		for (int i = 0; i < 2; i++) {
			if (this.numbers[i] != targetStatus[i]) {
				r = false;
				break;
			}
		}
		return r;
	}

	@Override
	public String toString() {
		String s = "G="+g+", H="+h+"\n";
		s += "\t{" + numbers[0] + ", " + numbers[1] + "}\n";
		return s;
	}

	
	public boolean betterThan(Status s) {
		boolean r = false;
		if (s instanceof Travel) {	
			Travel other = (Travel)s;
			if (this.g + this.h < other.g + other.h) {
				r = true;
			}  
		}
		return r;
	}
	
	private void setHValue() {
		h = 0;
		for (int i = 0; i < 2; i++) {
			h += Math.pow(numbers[i] - targetStatus[i], 2);
		}
		h = 10 * Math.sqrt(h);
	}
}